#ifndef  PROTOFILE
#define  PROTOFILE

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include "bt_mutex.h"

class ReadProtoFile
{
    public:
        ReadProtoFile(std::string filename)
        {
            fp = fopen(filename.c_str(), "rb");
        }
        virtual ~ReadProtoFile()
        {
            if(fp)
                fclose(fp);
        }
        
        template<typename a>
        bool GetProject(a & ta)
        {
            mutex_guard tmp(&m_locker);
            if(!fp)
            {
                return false;
            }
            std::string tp;
            int len;
            int readlen = fread(&len, 1, 4, fp);
            if(readlen != 4)
            {
                if(readlen != 0)
                {
                    std::cout << " read head wrong " << readlen << std::endl;
                }
                return false;
            }
            const int bufflen = 1024;
            char buff[bufflen] = { 0 };
            
            int datalen = 0;
            while(datalen != len)
            {
                int thistimeread = bufflen;
                if(len - datalen < bufflen)
                {
                    thistimeread = len - datalen;
                }
                int thistimereaded = 0;
                thistimereaded = fread(buff, 1, thistimeread, fp);
                
                if(thistimereaded <= 0)
                {
                    std::cout << " read data wrong " << thistimereaded
                            << " sumneed " << len << " readed " << datalen
                            << std::endl;
                    return false;
                }
                datalen += thistimereaded;
                
                tp.append(buff, thistimereaded);
                /*
                 char c;
                 
                 if (1 != fread(&c ,1 , 1, fp))
                 {
                 return false;
                 }
                 tp += c;
                 len--;
                 */
            }
            ta.ParsePartialFromString(tp);
            return true;
        }
        
    private:
        FILE * fp;
        mutex_block m_locker;
};

class WriteProtoFile
{
    public:
        WriteProtoFile(std::string filename)
        {
            fp = fopen(filename.c_str(), "ab");
            
            (void)(fseek(fp, 0, SEEK_END));
            m_size = 0;
        }
        virtual ~WriteProtoFile()
        {
            if(fp)
                fclose(fp);
        }
        const long long GetLen() const
        {
            return m_size;
        }
        
        template<typename a>
        bool SaveProject(const a & ta)
        {
            mutex_guard tmp(&m_locker);
            if(!fp)
            {
                return false;
            }

            std::string tp;
            ta.SerializeToString(&tp);
            int len = tp.length();
            fwrite(&len, 1, 4, fp);
            fwrite(tp.c_str(), 1, len, fp);
            //fflush(fp);
            ++m_size;
            return true;
        }
        
    private:
        FILE * fp;
        mutex_block m_locker;
        long long m_size;
        
};
#endif
